<?php

namespace app\modules\v1\controllers;

use app\modules\v1\components\BaseController;
use common\models\db\CommercialLoanDetail;
use common\models\db\EqualResult;
use common\models\db\FundLoanDetail;
use common\models\db\LoanRecord;
use common\models\db\PrincipalResult;
use common\models\db\SystemConfig;
use Yii;
use yii\db\Exception;

/**
 * 贷款计算相关接口
 */
class LoanController extends BaseController
{
    /**
     * 贷款计算 API
     * @return void
     */
    public function actionCalculate()
    {
        // 获取请求参数
        $type = $this->getPostData('type', '');
        $repaymentType = $this->getPostData('repaymentType', '');
        $years = intval($this->getPostData('years', 0));
        
        // 参数验证
        if (!in_array($type, ['commercial', 'fund', 'combined'])) {
            $this->error('贷款类型参数错误', 2001);
        }
        
        if (!in_array($repaymentType, ['equal', 'principal', 'compare'])) {
            $this->error('还款方式参数错误', 2001);
        }
        
        if ($years <= 0 || $years > 30) {
            $this->error('贷款年限参数错误', 2001);
        }
        
        // 根据贷款类型处理不同的参数
        $data = [
            'loanType' => $type,
            'repaymentType' => $repaymentType,
            'years' => $years,
            'totalAmount' => 0
        ];
        
        // 计算月数
        $months = $years * 12;
        
        // 商业贷款或公积金贷款
        if ($type == 'commercial' || $type == 'fund') {
            $amount = floatval($this->getPostData('amount', 0));
            $rate = floatval($this->getPostData('rate', 0));
            
            if ($amount <= 0) {
                $this->error('贷款金额参数错误', 2001);
            }
            
            if ($rate <= 0) {
                $this->error('贷款利率参数错误', 2001);
            }
            
            $adjustedRate = $rate;
            
            // 商业贷款可能有基点调整
            if ($type == 'commercial') {
                $basisPoints = intval($this->getPostData('basisPoints', 0));
                $adjustedRate = $rate + $basisPoints / 100;
            }
            
            $data['amount'] = $amount;
            $data['rate'] = $rate;
            $data['adjustedRate'] = $adjustedRate;
            $data['totalAmount'] = $amount;
            
            // 计算贷款结果
            $loanAmount = $amount * 10000; // 转换为元
            $monthlyRate = $adjustedRate / 100 / 12; // 月利率
            
            // 计算等额本息结果
            if ($repaymentType == 'equal' || $repaymentType == 'compare') {
                $equalResult = $this->calculateEqual($loanAmount, $monthlyRate, $months);
                $data['equalResult'] = $equalResult;
            }
            
            // 计算等额本金结果
            if ($repaymentType == 'principal' || $repaymentType == 'compare') {
                $principalResult = $this->calculatePrincipal($loanAmount, $monthlyRate, $months);
                $data['principalResult'] = $principalResult;
            }
            
            // 计算对比结果
            if ($repaymentType == 'compare') {
                $data['interestDiff'] = round($equalResult['totalInterest'] - $principalResult['totalInterest'], 2);
            }
        }
        // 组合贷款
        else if ($type == 'combined') {
            $commercialAmount = floatval($this->getPostData('commercialAmount', 0));
            $commercialRate = floatval($this->getPostData('commercialRate', 0));
            $fundAmount = floatval($this->getPostData('fundAmount', 0));
            $fundRate = floatval($this->getPostData('fundRate', 0));
            $commercialBasisPoints = intval($this->getPostData('commercialBasisPoints', 0));
            
            if ($commercialAmount <= 0) {
                $this->error('商业贷款金额参数错误', 2001);
            }
            
            if ($commercialRate <= 0) {
                $this->error('商业贷款利率参数错误', 2001);
            }
            
            if ($fundAmount <= 0) {
                $this->error('公积金贷款金额参数错误', 2001);
            }
            
            if ($fundRate <= 0) {
                $this->error('公积金贷款利率参数错误', 2001);
            }
            
            $adjustedCommercialRate = $commercialRate + $commercialBasisPoints / 100;
            
            $data['commercialAmount'] = $commercialAmount;
            $data['commercialRate'] = $commercialRate;
            $data['adjustedCommercialRate'] = $adjustedCommercialRate;
            $data['fundAmount'] = $fundAmount;
            $data['fundRate'] = $fundRate;
            $data['totalAmount'] = $commercialAmount + $fundAmount;
            
            // 计算商业贷款结果
            $commercialLoanAmount = $commercialAmount * 10000; // 转换为元
            $commercialMonthlyRate = $adjustedCommercialRate / 100 / 12; // 月利率
            
            // 计算公积金贷款结果
            $fundLoanAmount = $fundAmount * 10000; // 转换为元
            $fundMonthlyRate = $fundRate / 100 / 12; // 月利率
            
            // 计算等额本息结果
            if ($repaymentType == 'equal' || $repaymentType == 'compare') {
                $commercialEqualResult = $this->calculateEqual($commercialLoanAmount, $commercialMonthlyRate, $months);
                $fundEqualResult = $this->calculateEqual($fundLoanAmount, $fundMonthlyRate, $months);
                
                $equalResult = [
                    'totalLoan' => $commercialEqualResult['totalLoan'] + $fundEqualResult['totalLoan'],
                    'totalRepayment' => $commercialEqualResult['totalRepayment'] + $fundEqualResult['totalRepayment'],
                    'totalInterest' => $commercialEqualResult['totalInterest'] + $fundEqualResult['totalInterest'],
                    'monthlyPayment' => $commercialEqualResult['monthlyPayment'] + $fundEqualResult['monthlyPayment']
                ];
                
                $data['equalResult'] = $equalResult;
            }
            
            // 计算等额本金结果
            if ($repaymentType == 'principal' || $repaymentType == 'compare') {
                $commercialPrincipalResult = $this->calculatePrincipal($commercialLoanAmount, $commercialMonthlyRate, $months);
                $fundPrincipalResult = $this->calculatePrincipal($fundLoanAmount, $fundMonthlyRate, $months);
                
                $principalResult = [
                    'totalLoan' => $commercialPrincipalResult['totalLoan'] + $fundPrincipalResult['totalLoan'],
                    'totalRepayment' => $commercialPrincipalResult['totalRepayment'] + $fundPrincipalResult['totalRepayment'],
                    'totalInterest' => $commercialPrincipalResult['totalInterest'] + $fundPrincipalResult['totalInterest'],
                    'firstMonthPayment' => $commercialPrincipalResult['firstMonthPayment'] + $fundPrincipalResult['firstMonthPayment'],
                    'decreasePerMonth' => $commercialPrincipalResult['decreasePerMonth'] + $fundPrincipalResult['decreasePerMonth'],
                    'lastMonthPayment' => $commercialPrincipalResult['lastMonthPayment'] + $fundPrincipalResult['lastMonthPayment']
                ];
                
                $data['principalResult'] = $principalResult;
            }
            
            // 计算对比结果
            if ($repaymentType == 'compare') {
                $data['interestDiff'] = round($equalResult['totalInterest'] - $principalResult['totalInterest'], 2);
            }
        }
        
        // 如果用户已登录，自动保存计算结果到历史记录
        if ($this->user) {
            $recordId = $this->saveCalculationResult($type, $repaymentType, $years, $data);
            if ($recordId) {
                $data['recordId'] = $recordId;
            } else {
                // 记录保存失败，但不影响计算结果的返回
                Yii::error('自动保存计算结果失败');
                $data['saveError'] = '自动保存计算结果失败，请稍后重试';
            }
        }
//        var_dump($data);
        $this->success($data, '计算成功');
    }
    
    /**
     * 获取默认利率和利率选项 API
     * @return void
     */
    public function actionRateOptions()
    {
        try {
            // 获取商贷利率选项
            $commercialLprShort = SystemConfig::find()
                ->where(['config_key' => 'commercial_lpr_short'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_COMMERCIAL])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_SHORT])
                ->one();
                
            $commercialLprLong = SystemConfig::find()
                ->where(['config_key' => 'commercial_lpr_long'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_COMMERCIAL])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_LONG])
                ->one();
            
            // 获取公积金利率选项
            $fundRateShort = SystemConfig::find()
                ->where(['config_key' => 'fund_rate_short'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_FUND])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_SHORT])
                ->one();
                
            $fundRateLong = SystemConfig::find()
                ->where(['config_key' => 'fund_rate_long'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_FUND])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_LONG])
                ->one();
            
            // 获取默认利率
            $defaultCommercialRateShort = SystemConfig::find()
                ->where(['config_key' => 'default_commercial_rate_short'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_COMMERCIAL])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_SHORT])
                ->one();
                
            $defaultCommercialRateLong = SystemConfig::find()
                ->where(['config_key' => 'default_commercial_rate_long'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_COMMERCIAL])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_LONG])
                ->one();
                
            $defaultFundRateShort = SystemConfig::find()
                ->where(['config_key' => 'default_fund_rate_short'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_FUND])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_SHORT])
                ->one();
                
            $defaultFundRateLong = SystemConfig::find()
                ->where(['config_key' => 'default_fund_rate_long'])
                ->andWhere(['rate_type' => SystemConfig::RATE_TYPE_FUND])
                ->andWhere(['term_type' => SystemConfig::TERM_TYPE_LONG])
                ->one();
            
            // 检查配置是否存在
            $missingConfigs = [];
            if (!$commercialLprShort) $missingConfigs[] = 'commercial_lpr_short';
            if (!$commercialLprLong) $missingConfigs[] = 'commercial_lpr_long';
            if (!$fundRateShort) $missingConfigs[] = 'fund_rate_short';
            if (!$fundRateLong) $missingConfigs[] = 'fund_rate_long';
            if (!$defaultCommercialRateShort) $missingConfigs[] = 'default_commercial_rate_short';
            if (!$defaultCommercialRateLong) $missingConfigs[] = 'default_commercial_rate_long';
            if (!$defaultFundRateShort) $missingConfigs[] = 'default_fund_rate_short';
            if (!$defaultFundRateLong) $missingConfigs[] = 'default_fund_rate_long';
            
            if (!empty($missingConfigs)) {
                Yii::error('缺少系统配置项: ' . implode(', ', $missingConfigs));
                $this->error('系统配置不完整: ' . implode(', ', $missingConfigs), 500);
            }
            
            // 解析JSON配置
            $commercialLprShortArray = $this->parseJsonConfig($commercialLprShort->config_value, 'commercial_lpr_short');
            $commercialLprLongArray = $this->parseJsonConfig($commercialLprLong->config_value, 'commercial_lpr_long');
            $fundRateShortArray = $this->parseJsonConfig($fundRateShort->config_value, 'fund_rate_short');
            $fundRateLongArray = $this->parseJsonConfig($fundRateLong->config_value, 'fund_rate_long');
            $defaultCommercialRateShortArray = $this->parseJsonConfig($defaultCommercialRateShort->config_value, 'default_commercial_rate_short');
            $defaultCommercialRateLongArray = $this->parseJsonConfig($defaultCommercialRateLong->config_value, 'default_commercial_rate_long');
            $defaultFundRateShortArray = $this->parseJsonConfig($defaultFundRateShort->config_value, 'default_fund_rate_short');
            $defaultFundRateLongArray = $this->parseJsonConfig($defaultFundRateLong->config_value, 'default_fund_rate_long');
            
            $data = [
                'commercialLprShort' => $commercialLprShortArray,
                'commercialLprLong' => $commercialLprLongArray,
                'fundRateShort' => $fundRateShortArray,
                'fundRateLong' => $fundRateLongArray,
                'defaultCommercialRateShort' => isset($defaultCommercialRateShortArray[0]['value']) ? $defaultCommercialRateShortArray[0]['value'] : 3.95,
                'defaultCommercialRateLong' => isset($defaultCommercialRateLongArray[0]['value']) ? $defaultCommercialRateLongArray[0]['value'] : 4.20,
                'defaultFundRateShort' => isset($defaultFundRateShortArray[0]['value']) ? $defaultFundRateShortArray[0]['value'] : 2.60,
                'defaultFundRateLong' => isset($defaultFundRateLongArray[0]['value']) ? $defaultFundRateLongArray[0]['value'] : 3.10
            ];
            
            $this->success($data, '获取成功');
        } catch (\Exception $e) {
            Yii::error('获取利率选项异常: ' . $e->getMessage());
            $this->error('获取利率选项失败: ' . $e->getMessage(), 500);
        }
    }
    
    /**
     * 解析JSON配置
     * @param string $jsonString JSON字符串
     * @param string $configKey 配置键名(用于错误日志)
     * @return array 解析后的数组
     */
    private function parseJsonConfig($jsonString, $configKey)
    {
        $result = json_decode($jsonString, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            Yii::error("解析{$configKey}配置JSON失败: " . json_last_error_msg());
            return [];
        }
        return $result;
    }
    
    /**
     * 计算等额本息结果
     * @param float $loanAmount 贷款金额(元)
     * @param float $monthlyRate 月利率
     * @param int $months 贷款月数
     * @return array
     */
    private function calculateEqual($loanAmount, $monthlyRate, $months)
    {
        // 计算月供
        $monthlyPayment = $loanAmount * $monthlyRate * pow(1 + $monthlyRate, $months) / (pow(1 + $monthlyRate, $months) - 1);
        
        // 计算还款总额
        $totalRepayment = $monthlyPayment * $months;
        
        // 计算总利息
        $totalInterest = $totalRepayment - $loanAmount;
        
        return [
            'totalLoan' => round($loanAmount, 2),
            'totalRepayment' => round($totalRepayment, 2),
            'totalInterest' => round($totalInterest, 2),
            'monthlyPayment' => round($monthlyPayment, 2)
        ];
    }
    
    /**
     * 计算等额本金结果
     * @param float $loanAmount 贷款金额(元)
     * @param float $monthlyRate 月利率
     * @param int $months 贷款月数
     * @return array
     */
    private function calculatePrincipal($loanAmount, $monthlyRate, $months)
    {
        // 每月本金
        $monthlyPrincipal = $loanAmount / $months;
        
        // 首月利息
        $firstMonthInterest = $loanAmount * $monthlyRate;
        
        // 首月还款
        $firstMonthPayment = $monthlyPrincipal + $firstMonthInterest;
        
        // 每月递减
        $decreasePerMonth = $monthlyPrincipal * $monthlyRate;
        
        // 末月利息
        $lastMonthInterest = $monthlyPrincipal * $monthlyRate;
        
        // 末月还款
        $lastMonthPayment = $monthlyPrincipal + $lastMonthInterest;
        
        // 总利息 = (首月利息 + 末月利息) * 月数 / 2
        $totalInterest = ($firstMonthInterest + $lastMonthInterest) * $months / 2;
        
        // 还款总额
        $totalRepayment = $loanAmount + $totalInterest;
        
        return [
            'totalLoan' => round($loanAmount, 2),
            'totalRepayment' => round($totalRepayment, 2),
            'totalInterest' => round($totalInterest, 2),
            'firstMonthPayment' => round($firstMonthPayment, 2),
            'decreasePerMonth' => round($decreasePerMonth, 2),
            'lastMonthPayment' => round($lastMonthPayment, 2)
        ];
    }
    
    /**
     * 保存计算结果到历史记录表
     * @param string $type 贷款类型
     * @param string $repaymentType 还款方式
     * @param int $years 贷款年限
     * @param array $data 计算结果数据
     * @return int|null 记录ID，失败返回null
     */
    private function saveCalculationResult($type, $repaymentType, $years, $data)
    {
        // 开启事务
        $transaction = Yii::$app->db->beginTransaction();
        
        try {
            // 创建贷款记录
            $record = new LoanRecord();
            $record->user_id = $this->user->id;
            $record->loan_type = $type;
            $record->repayment_type = $repaymentType;
            $record->years = $years;
            $record->total_amount = $data['totalAmount'];
            $record->created_at = date('Y-m-d H:i:s');
            
            if (!$record->save()) {
                $errors = $record->getErrors();
                $errorMsg = '保存贷款记录失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                throw new \Exception($errorMsg);
            }
            
            // 根据贷款类型保存详情
            if ($type == 'commercial') {
                $commercial = new CommercialLoanDetail();
                $commercial->record_id = $record->id;
                $commercial->amount = $data['amount'];
                $commercial->rate = $data['rate'];
                $commercial->basis_points = $this->getPostData('basisPoints', 0);
                $commercial->adjusted_rate = $data['adjustedRate'];
                
                if (!$commercial->save()) {
                    $errors = $commercial->getErrors();
                    $errorMsg = '保存商业贷款详情失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                    throw new \Exception($errorMsg);
                }
            } else if ($type == 'fund') {
                $fund = new FundLoanDetail();
                $fund->record_id = $record->id;
                $fund->amount = $data['amount'];
                $fund->rate = $data['rate'];
                
                if (!$fund->save()) {
                    $errors = $fund->getErrors();
                    $errorMsg = '保存公积金贷款详情失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                    throw new \Exception($errorMsg);
                }
            } else if ($type == 'combined') {
                $commercial = new CommercialLoanDetail();
                $commercial->record_id = $record->id;
                $commercial->amount = $data['commercialAmount'];
                $commercial->rate = $data['commercialRate'];
                $commercial->basis_points = $this->getPostData('commercialBasisPoints', 0);
                $commercial->adjusted_rate = $data['adjustedCommercialRate'];
                
                if (!$commercial->save()) {
                    $errors = $commercial->getErrors();
                    $errorMsg = '保存商业贷款详情失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                    throw new \Exception($errorMsg);
                }
                
                $fund = new FundLoanDetail();
                $fund->record_id = $record->id;
                $fund->amount = $data['fundAmount'];
                $fund->rate = $data['fundRate'];
                
                if (!$fund->save()) {
                    $errors = $fund->getErrors();
                    $errorMsg = '保存公积金贷款详情失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                    throw new \Exception($errorMsg);
                }
            }
            
            // 保存等额本息结果
            if (isset($data['equalResult'])) {
                $equal = new EqualResult();
                $equal->record_id = $record->id;
                $equal->total_loan = $data['equalResult']['totalLoan'];
                $equal->total_repayment = $data['equalResult']['totalRepayment'];
                $equal->total_interest = $data['equalResult']['totalInterest'];
                $equal->monthly_payment = $data['equalResult']['monthlyPayment'];
                
                if (!$equal->save()) {
                    $errors = $equal->getErrors();
                    $errorMsg = '保存等额本息结果失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                    throw new \Exception($errorMsg);
                }
            }
            
            // 保存等额本金结果
            if (isset($data['principalResult'])) {
                $principal = new PrincipalResult();
                $principal->record_id = $record->id;
                $principal->total_loan = $data['principalResult']['totalLoan'];
                $principal->total_repayment = $data['principalResult']['totalRepayment'];
                $principal->total_interest = $data['principalResult']['totalInterest'];
                $principal->first_month_payment = $data['principalResult']['firstMonthPayment'];
                $principal->decrease_per_month = $data['principalResult']['decreasePerMonth'];
                $principal->last_month_payment = $data['principalResult']['lastMonthPayment'];
                
                if (!$principal->save()) {
                    $errors = $principal->getErrors();
                    $errorMsg = '保存等额本金结果失败: ' . json_encode($errors, JSON_UNESCAPED_UNICODE);
                    throw new \Exception($errorMsg);
                }
            }
            
            $transaction->commit();
            
            return $record->id;
        } catch (\Exception $e) {
            $transaction->rollBack();
            Yii::error('自动保存计算结果失败: ' . $e->getMessage());
            return null;
        }
    }
} 